﻿using System;
using System.Collections.Generic;
using System.Net.Mail;
using System.Text;
using System.Xml.Linq;

namespace ICalendar
{
    internal class Util
    {
        public static void Read(string input, out string propName, out string value, out XParameterCollection xparams)
        {
            if (string.IsNullOrEmpty(input))
            {
                propName = null;
                value = null;
                xparams = new XParameterCollection();
                return;
            }

            if (input.EndsWith("\r\n"))
                input = input.Remove(input.Length - 2, 2);

            input = input.UnFolding();

            var propvalue = input.Split(new[] { ':' }, 2);

            value = propvalue.GetUpperBound(0) == 1 ? propvalue[1].UnEscape() : null;

            var propXparams = propvalue[0].Split(';');
            propName = propXparams[0].ToUpperInvariant();

            xparams = new XParameterCollection();
            for (var i = 1; i < propXparams.Length; i++)
            {
                var resultXparam = propXparams[i].Split(new[] { '=' }, 2);
                if (resultXparam.GetUpperBound(0) < 0) continue;
                var xparamName = resultXparam[0].ToUpperInvariant();
                var xparamValue = resultXparam.GetUpperBound(0) == 1 ? resultXparam[1].UnEscape() : null;
                xparams.Add(xparamName, xparamValue);
            }
        }

        public static string Write(string propName, object value, XParameterCollection xparams, bool escapedValue)
        {

            if (value == null)
                return null;

            var strXparams = new StringBuilder();
            
            if (xparams != null)
            {
                foreach (var xparam in xparams)
                {
                    if (!string.IsNullOrEmpty(xparam.Value) && xparam.Value != "\"\"")
                        strXparams.AppendFormat(";{0}={1}", xparam.Key, xparam.Value.Escape());
                }
            }

            var line = string.Format("{0}{1}:{2}", propName, strXparams, escapedValue ? Convert.ToString(value).Escape() : Convert.ToString(value));

            line = line.Folding();

            // Write the line out
            return line + "\r\n";
        }

        public static string Write(String propName, Object value, char splitChar)
        {
            if (value == null)
                return null;

            var line = propName + splitChar + Convert.ToString(value).Escape();

            line = line.Folding();
            // Write the line out
            return line + "\r\n";
        }

        public static string Write(String propName, Object value)
        {
            return Write(propName, value, ':');
        }
        
        public static string GetTriggerString(object trigger, TriggerRelationship triggerRelationship)
        {
            //Trigger
            string strTrigger;
            if (trigger is DateTime) //ABSOLUTE
            {
                strTrigger = Write("TRIGGER", ((DateTime)trigger).ToICalendarUniversalTimeString(), new XParameterCollection { { "VALUE", "DATE-TIME" } }, true);
            }
            else //RELATIVE
            {
                var xparam = new XParameterCollection();
                if (triggerRelationship == TriggerRelationship.End)
                {
                    xparam.Add("RELATED", "END");
                }

                strTrigger = Write("TRIGGER", ((Duration)trigger).ToString(), xparam, true);
            }
            return strTrigger;
        }

        public static MailAddress FromCalAddressAndCommonName(string address, string commonName)
        {
            return address != null ? new MailAddress(address.Replace("mailto:", ""), commonName != null ? commonName.Replace("\"", "") : null) : null;
        }
    }
}

